package yl.hs.bmipfull.daos.production;

import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import yl.hs.bmipfull.daos.BaseDao;
import yl.hs.bmipfull.pojo.customize.ProductionTaskCumulative;
import yl.hs.bmipfull.pojo.finance.ShipSettleTemp;
import yl.hs.bmipfull.pojo.production.ProductShipOrderEntity;
import yl.hs.bmipfull.viewmodels.base.StringDecimalModel;
import yl.hs.bmipfull.viewmodels.dataCockpit.DataCockpitNumberModel;
import yl.hs.bmipfull.viewmodels.dataCockpit.EngineeringVo;
import yl.hs.bmipfull.viewmodels.production.ProductShipOrderDCYUZLEntity;
import yl.hs.bmipfull.viewmodels.report.MonthlySalesReportVO;
import yl.hs.bmipfull.viewmodels.salemanmage.SetTimeVO;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 作用:  产品发货单持久层接口<br/>
 * 创建时间: 2021年06月21日 10时08分52秒 <br/>
 *
 * @author 谢东
 */
@Repository
public interface IProductShipOrderDao extends BaseDao<ProductShipOrderEntity> {


    /**
     * 分页查询产品发货单信息
     *
     * @param map 查询条件 {@link ProductShipOrderEntity}
     * @return 站内信息-List<{@link ProductShipOrderEntity}>
     */
    List<ProductShipOrderEntity> queryPage(@Param("map") Map<String, Object> map, String productCateSN,@Param("filters") List<Map<String,Object>> filters,List<Integer> states);


    String weightStatisticsByDay(@Param("startDate") Date startDate, @Param("endDate") Date endDate, @Param("companyName") String companyName);


    /**
     * 根据查询条件统计数据数量
     *
     * @param map 查询条件
     * @return 数据数量
     */
    Integer queryCountByCondition(@Param("map") Map<String, Object> map,String productCateSN,@Param("filters") List<Map<String,Object>> filters,List<Integer> states);

    /**
     * 信息编号删除
     *
     * @param snArray 数据编号
     * @param state   要改变的状态
     * @return s
     */
    Integer changeStateBySN(String[] snArray, short state);

    /**
     *  修改发货单开票状态
     * @param snArray 编号
     * @param state 状态
     * @return 受影响行数
     */
    Integer changeInvoicingStateBySN(String[] snArray, short state);

    /**
     * 获取某天生产方量
     *
     * @param date 日期
     * @return 生产方量
     */
    double getDayVolume(Date date, String productCateSN);

    /**
     * 获取某月生产方量
     *
     * @param date 日期
     * @return 生产方量
     */
    double getMonthVolume(Date date, String productCateSN);

    /**
     * 根据任务单号获取生产方量
     *
     * @param snArray 任务单号
     * @return 生产方量
     */
    double getVolumeByTaskSN(List<String> snArray);

    /**
     * 根据合同查询此合同下发货方量
     *
     * @param contractSN 合同编号
     * @return 发货方量
     */
    double findQuantityByContractSN(String contractSN);

    /**
     * 根据任务单号获取此任务单的最后一张发货单据
     *
     * @param taskSN 任务单号
     * @return 发货单
     */
    ProductShipOrderEntity findListByTaskSN(String taskSN);

    List<ProductShipOrderEntity> findListByTaskSNList(List<String> snList);

    /**
     * 根据状态，条数，排序字段查询发货单信息
     *
     * @param state 状态
     * @param top   条数
     * @param sort  排序字段
     * @return 发货单
     */

    List<ProductShipOrderEntity> findByState(short state, int top, String sort, Object key, String productCateSN);

    /**
     * 根据任务单号获取此任务单的第一张发货单据
     *
     * @param taskSN 任务单号
     * @return 发货单
     */
    ProductShipOrderEntity findListByTaskSNASC(String taskSN);

    /**
     * 根据车辆编号查询该车辆最新发货单信息
     *
     * @param truckCode 车辆编号
     * @return 发货单
     */

    ProductShipOrderEntity findListByTruckCode(String truckCode);

    /**
     * 根据生产任务编号
     *
     * @param map 任务编号
     * @return 发货单
     */
    List<ProductShipOrderEntity> getListByProductionTaskSN(@Param("map") Map<String, Object> map,@Param("productCateSN") String productCateSN,@Param("filters") List<Map<String,Object>> filters);

    /**
     * 根据任务单号和车辆编号获取平均车辆运输时间
     *
     * @param taskSN  任务单号
     * @return 运输时间（min）
     */
    List<StringDecimalModel> getAVGTransTimeByTaskSNAndTruckSN(String taskSN);

    /**
     * 根据任务单号和车辆编号和发货类型获取发货次数
     *
     * @param taskSN    任务单号
     * @param truckSN   车辆编号
     * @return 发货次数
     */
    Integer getCountByTaskSNAndTruckSNAndOrderType(String taskSN, String truckSN);

    /**
     * 根据任务单号和车辆编号获取发货数量
     *
     * @param taskSN  任务单号
     * @return 数量
     */
    List<StringDecimalModel> getSumNetWeightByTaskSNAndTruckSN(String taskSN);

    /**
     * 根据车辆派车类型以及车辆自编号查询上车发货单信息
     *
     * @param productCateSN 单据类型编号
     * @param truckCode 车辆编号
     * @return 单据信息
     */
    ProductShipOrderEntity findByOrderType(String productCateSN, String truckCode);

    /**
     * 根据车辆派车类型以及生产任务sn查询上车发货单信息
     *
     * @param productCateSN 产品类别编号
     * @param taskSN    生产任务sn
     * @return 单据信息
     */
    ProductShipOrderEntity findByTaskSn(String productCateSN, String taskSN);

    /**
     * 根据车辆编号及单据状态查询单据信息
     *
     * @param truckCode 车辆自编号
     * @param state     状态
     * @return 单据信息
     */
    List<ProductShipOrderEntity>  findByTruckCodeState(String truckCode, short state);
    @Select("SELECT * FROM product_ship_order WHERE state = #{state}")
    List<ProductShipOrderEntity>  queryByState(short state);
    /**
     * 根据生产线获取发货单信息
     * @param lineSn 生产线sn
     * @return 发货单信息
     */
    @Select("select * from product_ship_order where lineSN = #{lineSn} and state != -1")
    List<ProductShipOrderEntity> queryByLineSn(String lineSn);

    /**
     * 根据发货类型时间查询发货单
     * @param productCateSN 产品类别编号，time 时间
     * @return 发货单信息
     */
    @Select("select * from product_ship_order where productCateSN = #{productCateSN} and outTime > #{time}")
    List<ProductShipOrderEntity> questListByType(String productCateSN,Date time);

    Integer updateOrderToReviewed(@Param("snList") List<String> orderSnList, @Param("userSN")String userSN, @Param("userName")String userName, @Param("review") boolean review,@Param("code") short state);
    /**
     * 根据合同编号和发货时间获取总金额
     * @param contractSN 合同编号，outTime 时间
     * @return 发货单信息
     */
    @Select("select ifnull(sum(getProductPrice(contractSN, productSN, outTime, productTags)),0) as price FROM product_ship_order WHERE state!=2 and state!=0 and contractSN =#{contractSN}  and outTime >=#{outTime}")
    double queryPrice(String contractSN,Date outTime);





    @Select("select ifnull(sum(quantity),0) as weight FROM product_ship_order WHERE state>0 and contractSN =#{contractSN}  and outTime >=#{outTime}")
    double queryOrderWeight(String contractSN,Date outTime);
    double querySaleGroupDay(String productCateSN,String startTime,String endTime,List<String> lineSNList);

    /**
     * 根据合同编号获取发货单信息
     * @param contractSn 合同sn
     * @return 发货单信息
     */
    List<ShipSettleTemp> queryByContractSn(String contractSn);

    /**
     *  根据产品编号分组进行查询
     * @param map 查询参数
     * @return 数据
     */
    List<ProductShipOrderEntity> queryGroupByProductSN(@Param("map") Map<String, Object> map,String productCateSN,@Param("filters") List<Map<String,Object>> filters,List<Integer> states);

    /**
     * 获取发货单的发货年份和月份
     * @return 时间
     */
    List<SetTimeVO> getSetTime();

    List<MonthlySalesReportVO> getMonthlySalesReport(@Param("map") Map<String, Object> map, String productCateSN, @Param("filters") List<Map<String,Object>> filters, List<Integer> states);

    Integer getMonthlySalesReportCount(@Param("map") Map<String, Object> map, String productCateSN, @Param("filters") List<Map<String,Object>> filters, List<Integer> states);

    /**
     * 获取发货量
     * @param cateSn 产品编号
     * @param type 1.本月   2.当天
     * @return 发货量
     */
    BigDecimal getDeliveringAmount(String cateSn,int type);

    /**
     * 获取未审核
     * @return 行数
     */
    @Select("SELECT COALESCE(COUNT(0),0) FROM product_ship_order WHERE  state=1")
    Integer getNotApproved();
    /**
     * 获取未审核
     * @return 行数
     */
    @Select("SELECT COALESCE(SUM(NetWeight),0) FROM product_ship_order WHERE  state>0 AND taskSN=#{taskSn}")
    BigDecimal getSumNetWeightByTask(String taskSn);

    @Select("SELECT COALESCE(COUNT(0),0) FROM product_ship_order WHERE  state>0 AND taskSN=#{taskSn}")
    Integer getTruckCountByTask(String taskSn);

    /**
     * 获取已审核单据金额
     * @return 汇总
     */
    @Select("SELECT COALESCE(SUM(getProductPrice ( contractSN, productSN, outTime, productTags )*quantity),0) from product_ship_order where state=10")
    BigDecimal getExamineQuantity();

    BigDecimal getControlShipQuantityCount(@Param("htSN")String htSN,@Param("startTime") Date startTime);


    BigDecimal getControlShipAmountCount(@Param("htSN")String htSN,@Param("startTime") Date startTime);

    List<ProductShipOrderEntity> getByProjectByMonth();
    @Select("select contractSN FROM product_ship_order WHERE  !ISNULL(contractSN) and state>=1 and productCateSN=#{cateSN}  GROUP BY contractSN")
    List<String> getContractSNByCateSN(String cateSN);

    /**
     *  根据日期、生产线编号、产品种类编号获取数量的汇总
     * @param dateType 日期类型 1日 2周 3月
     * @param date 日期
     * @param lineSN 生产线编号
     * @return SumQuantity
     */
    BigDecimal getSumQuantityByLineSNAndDate(int dateType,String date,String lineSN);

    BigDecimal getProductSalesCurveByDate(int dateType,String date,String productCateSN);

    /**
     * 获取车辆的暂存信息
     * @param truck 车牌号
     * @return 暂存信息
     */
    ProductShipOrderEntity findTruckOrderDraft(@Param("truck") String truck);

    /**
     * 获取车辆最后一次运输的发货单
     * @param truckPlate 车牌号
     * @return 发货单信息
     */
    ProductShipOrderEntity findTruckLastOrder(@Param("truck") String truckPlate);

    /**
     * 获取产品价格信息
     * @param htSN 合同编号
     * @param pSN 产品编号
     * @param pTags 生产附加参数
     * @return 价格
     */
    BigDecimal getProductPrice(@Param("htSN") String htSN,@Param("pSN") String pSN,@Param("outTime") Date outTime,@Param("pTags") String pTags);

    /**
     * 根据合并单号获取所有发货单
     * @param mergeSN 合并单号
     * @return 发货单集合
     */
    List<ProductShipOrderEntity> queryByMergeSN(@Param("mergeSN")String mergeSN);

    /**
     * 删除生成完整发货单后的暂存信息
     * @param id 暂存发货单主键
     * @return 删除结果
     */
    Integer deleteTempOrder(@Param("id")Long id);

    /**
     * 获取生产任务的累计信息
     * @param taskSN 生产任务编号
     * @return 累计信息；
     */
    ProductionTaskCumulative getProTaskCumulative(@Param("taskSN") String taskSN);

    /**
     * 获取工地用户关联的发货单数量
     * @param query 搜索条件
     * @param snList 关联的合同编号
     * @param states 发货单状态
     * @return 发货单数量
     */
    Integer queryCountByCustom(@Param("map") Map<String, Object> query, @Param("snList") List<String> snList,@Param("states")  List<Integer> states,String productCateSN,@Param("filters") List<Map<String,Object>> filters);

    /**
     * 获取工地用户关联的发货单分页结果
     * @param query 搜索条件
     * @param snList 关联的合同编号
     * @param states 发货单状态
     * @return 发货单集合
     */
    List<ProductShipOrderEntity> queryDataByCustom(@Param("map") Map<String, Object> query, @Param("snList") List<String> snList, @Param("states") List<Integer> states,String productCateSN,@Param("filters") List<Map<String,Object>> filters);

    Integer updateOrderFreightReviewed(@Param("snList") List<String> orderSnList, String userSN, String userName, boolean review);

    double selectSumByCateSNAndDate(String productCateSN,Date date,int dateType);

    double selectSumAmountByCateSNAndDate(String productCateSN,Date date,int dateType);

    ProductShipOrderEntity selectProduct();
    List<ProductShipOrderDCYUZLEntity> selectProductNetWeight(int dateType);


    double saleNetWeightTrendByMonth(Date datetime);

    List<DataCockpitNumberModel> selectSumNetWeightGroupProduct(Date date, int dateType);

    List<ProductShipOrderEntity> queryByTime(@Param("startTime") Date startTime);

    List<EngineeringVo> weightAnalysis();

    List<EngineeringVo> customerRanking(String timeType);

    List<EngineeringVo> regionalDelivery();

    List<EngineeringVo> thermalMap();

    String getOutputValue(String betonSysCode, String timeType);

    String getPeriod(String betonSysCode, String timeType);

    Double getMonthlyOutputValue(Date datetime);

    Object getPurchaseTrend(Date time);

    Integer updateFile(@Param("file") String file,@Param("id") long id);

    @MapKey("id")
    List<Map<String, Object>> findOldOrders();

    Integer updateInvoicingStateBySNList(int state,List<String> snList);

    BigDecimal quantity(List<String> snList);

    BigDecimal cumulative(List<String> snList);

    BigDecimal cumulativeMoney(List<String> snList);

    BigDecimal settled(List<String> snList);

    BigDecimal settledMoney(List<String> snList);

    BigDecimal signedIn(List<String> snList);

    BigDecimal unsigned(List<String> snList);

    BigDecimal money(List<String> snList);

    BigDecimal balance(List<String> snList);

    BigDecimal weightMonthly(List<String> snList, Date time);

    BigDecimal ReviewedMoneyMonthly(List<String> snList, Date time);

    BigDecimal unapprovedMoneyMonthly(List<String> snList, Date time);

    List<ProductShipOrderEntity>
    queryListByTimeAndUnit(@Param("unit") String unit,
                           @Param("cateSN") String cateSN,
                           @Param("start") Date startTime,
                           @Param("end") Date endTime);

    List<ShipSettleTemp> queryTimeRangeCateOrders(@Param("cateSN")String cateSN, @Param("start") Date startTime, @Param("end") Date endTime);
    List<ShipSettleTemp> queryTimeRangeProjectCateOrders(@Param("cateSN")String cateSN,@Param("projectSN")String projectSN, @Param("start") Date startTime, @Param("end") Date endTime);

    List<ProductShipOrderEntity> queryListByOrderSNList(List<String> snList);

    List<ProductShipOrderEntity> queryLastOrderListByTruckSNList(List<String> snList);

    double getTimeRangeVolume(@Param("start") Date startTime,@Param("end") Date endTime,@Param("cateSN") String productCateSN);

    BigDecimal queryMonthQuantity(String unit,@Param("cateSN") String cateSN,@Param("start") Date startTime,@Param("end") Date endTime);

    List<StringDecimalModel> queryLineShipQuantity(@Param("lineSNList") List<String> lineSN, @Param("start") Date start, @Param("end") Date end);

    ProductShipOrderEntity getAllProjectsAndTruckCodesByDate(@Param("companyName") String companyName, @Param("startDate") Date startDate, @Param("endDate") Date endDate);

    String queryWeightCountByCarAndProjectAndDate(@Param("companyName") String companyName,
                                                  @Param("truckCode") String truckCode,
                                                  @Param("projectName") String projectName,
                                                  @Param("startDate") Date startDate,
                                                  @Param("endDate") Date endDate);

}